package com.bluesky.plum.uimodels.standard.components;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;

import com.bluesky.plum.uimodels.standard.UIComponent;
import com.bluesky.plum.uimodels.standard.components.listbox.SelectionMode;
import com.bluesky.plum.uimodels.standard.components.listbox.Selector;

/**
 * ListBox must have list items. Items are entities. id, name pair is common.
 * id, description pair, description contains other information besides name id,
 * name, xxx, fff, ... etc. it is a table actually.
 * 
 * @author HZ00260
 * 
 */
public class ListBox<T> extends UIComponent implements Selector<T> {

	
	protected int defaultSelectedIndex=0;

	// data
	protected List<Object> data = new ArrayList<Object>();
	protected List<T> objects = new ArrayList<T>();

	protected ObjectEqualor objectEqualor = new ObjectEqualor() {
		@Override
		public boolean equals(Object obj1, Object obj2) {

			return obj1.equals(obj2);
		}
	};

	// event
	protected EventListener selectChangeListener;

	// mode
	protected SelectionMode selectionMode;

	public List<Object> getData() {
		return data;
	}

	public void setData(List<Object> data) {
		this.data = data;
	}

	public void setObjects(List<T> objects) {

		this.objects.clear();

		this.data.clear();

		for (T o : objects) {
			this.objects.add(o);

			Object fieldValue;
			try {
				fieldValue = PropertyUtils.getProperty(o, "name");
			} catch (Exception e) {

				// e.printStackTrace();
				fieldValue = o.toString();
			}

			this.data.add(fieldValue);
		}
		
		//set default value
		setSelectedIndex(defaultSelectedIndex);
	}

	public void selectChange() {
		if (selectChangeListener != null)
			selectChangeListener.process();
	}

	public void addObject(T t) {
		data.add(t);
	}

	@Override
	public List<T> getObjects() {

		return objects;
	}

	public EventListener getSelectChangeListener() {
		return selectChangeListener;
	}

	public void setSelectChangeListener(EventListener selectChangeListener) {
		this.selectChangeListener = selectChangeListener;
	}

	public ListBox() {

	}

	@Override
	public String toString() {
		if (data.isEmpty())
			return super.toString();

		StringBuilder sb = new StringBuilder();
		sb.append("(");
		for (Object o : data) {
			sb.append(o);
			sb.append("|");
		}
		sb.replace(sb.length() - 1, sb.length(), ")");

		return super.toString() + sb.toString();
	}

	public int getSelectedIndex() {
		return -1;
	}

	public void setSelectedIndex(int index) {

	}

	public int[] getSelectedIndices() {
		return null;
	}

	public void setSelectedIndices(int[] indices) {

	}

	public T getSelectedValue() {
		int idx = getSelectedIndex();
		if (idx == -1)
			return null;
		else
			return objects.get(getSelectedIndex());
	}

	public T[] getSelectedValues() {
		List<T> selectValues = new ArrayList<T>();

		int[] indices = getSelectedIndices();
		if(indices==null)
		{
			System.out.println("error");
			indices = getSelectedIndices();
		}
		for (int idx : indices) {
			T o = objects.get(idx);
			selectValues.add(o);
		}

		return (T[]) selectValues.toArray();
	}

	public void setSelectedValue(Object value) {
		for (int i = 0; i < objects.size(); i++) {

			if (objectEqualor.equals(objects.get(i), value)) {
				setSelectedIndex(i);
				return;
			}
		}
		throw new RuntimeException("value to set do not exist:" + value);
	}

	public void setSelectedValues(T[] values) {

		int[] indices = new int[values.length];
		for (int i = 0; i < values.length; i++)
			indices[i] = objects.indexOf(values[i]);

		setSelectedIndices(indices);
	}

	public SelectionMode getSelectionMode() {
		return selectionMode;
	}

	public void setSelectionMode(SelectionMode selectionMode) {
		this.selectionMode = selectionMode;
	}

	public ObjectEqualor getObjectEqualor() {
		return objectEqualor;
	}

	public void setObjectEqualor(ObjectEqualor objectEqualor) {
		this.objectEqualor = objectEqualor;
	}

}
